/*
 * Copyright (C) 2012-2013 Matthias Zeimer and the miniframes project group.
 * All rights reserved. 
 * 
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/EPL-1.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.miniframes.minivalues;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * <p>
 * A test helper to verify the restrictions for a value class in the values
 * class' unit-test.
 * </p>
 * 
 * <p>
 * Default usage (let {@code YourValueType} be the type to verify):
 * 
 * <pre>
 * new ValueVerifier( YourValueType.class ).verifyAllRestrictions();
 * </pre>
 * </p>
 * 
 * <p>
 * Unless otherwise noted, passing a null argument to any method may result in a
 * {@link NullPointerException}.
 * </p>
 * 
 * @author Matthias Zeimer
 * @version 1
 * @since 0.1, 06.06.2013
 */
public final class ValueVerifier<V extends Value<V>> {

    private final Class<V> valueClass;

    /**
     * <p>
     * Creates a new verifier for the specified value class.
     * </p>
     * 
     * @param valueClass
     *            The {@link Class} of the value to verify not {@code null}.
     * @throws NullPointerException
     *             if {@code valueClass} is {@code null}.
     */
    public ValueVerifier(Class<V> valueClass) throws NullPointerException {
        this.valueClass = valueClass;

        // TODO
    }

    /**
     * 
     * TODO ADD: Note: if you like to use a public constructor instead of a
     * factory method you need to call ... yourself instead of this method (this
     * skips the verification ...).
     * 
     * 
     * @throws InvalidValueClassDeclarationException
     */
    public void verifyAllRestrictions()
            throws InvalidValueClassDeclarationException {
        this.verifyClassRules();
        this.verifyFieldRules();
        this.verifyFieldTypeRules();
        this.verifyConstructorPassAllProperties();
        this.verifyConstructorForSerialisation();
    }

    public ValueVerifier<V> verifyClassRules() {
        // TODO
        return this;
    }

    public ValueVerifier<V> verifyFieldRules()
            throws InvalidValueClassDeclarationException {

        for (Field eachField : this.valueClass.getDeclaredFields()) {
            if (!Modifier.isFinal(eachField.getModifiers())) {
                throw new InvalidValueClassDeclarationException();
            }
        }

        // TODO
        return this;
    }

    public ValueVerifier<V> verifyFieldTypeRules() {
        // TODO
        return this;
    }

    public ValueVerifier<V> verifyConstructorPassAllProperties() {
        // TODO
        return this;
    }

    public ValueVerifier<V> verifyConstructorForSerialisation() {
        // TODO Present, calls super(), initialise fields with Java default
        return this;
    }

    // TODO test helper for serialisation tests!
}
